<?php
/**
 * @author qingyu8@staff.weibo.com
 * @date 2018/02/01
 */
namespace api\modules\v1\controllers;

use common\logic\Fund;
use common\logic\Order;
use common\logic\Sms;
use common\tool\Alarm;
use yii\filters\Cors;
use yii\filters\VerbFilter;
use Yii;
use api\models\User;
use yii\web\Controller;
use yii\web\Response;

class UserController extends Controller {
    public $enableCsrfValidation = false;

    public function behaviors() {
        return [
            'verbFilter' => [
                'class' => VerbFilter::className(),
                'actions' => $this->verbs(),
            ],
            'corsFilter' => [
                'class' => Cors::className(),
                'cors' => [
                    'Origin' => ['*'],
                    'Access-Control-Request-Method' => [
                        'GET',
                        'POST',
                        'HEAD',
                        'OPTIONS'
                    ],
                    'Access-Control-Max-Age' => 86400,
                    'Access-Control-Allow-Credentials' => true,
                ],
            ],
        ];
    }

    protected function verbs() {
        return [
            'login' => ['POST'],
            'logout' => ['POST'],
            'smsrequest' => ['POST'],
            'smsverify' => ['POST'],
            'info' => [
                'GET',
                'POST'
            ],
        ];
    }

    public function beforeAction($action) {
        Yii::$app->response->format = Response::FORMAT_JSON;
        return parent::beforeAction($action);
    }

    public function actionInfo() {
        if (Yii::$app->user->isGuest) {
            return [
                'code' => 403,
                '请先登录'
            ];
        }
        $method = Yii::$app->request->getMethod();
        /** @var \api\models\User $user */
        $user = Yii::$app->user->getIdentity();
        if ($method == 'GET') {
            $birthday = $user->getAttribute('birthday');
            $birthday == '1000-01-01' && $birthday = '';
            $openId = Yii::$app->session->get('wechat_openid');
            return [
                'code' => 200,
                'data' => [
                    'uid' => $user->getAttribute('uid'),
                    'username' => $user->getAttribute('username'),
                    'nickname' => $user->getAttribute('nickname'),
                    'email' => $user->getAttribute('email'),
                    'gender' => $user->getAttribute('gender'),
                    'phone' => substr_replace($user->getAttribute('phone'), '****', -8, 4),
                    'birthday' => $birthday,
                    'openid'=>$openId?:'',
                ]
            ];
        } else {
            $email = Yii::$app->request->post('email');
            $nickname = Yii::$app->request->post('nickname');
            $birthday = Yii::$app->request->post('birthday');
            if (empty($email) && empty($nickname) && empty($birthday)) {
                return [
                    'code' => 400,
                    'msg' => '参数错误',
                ];
            }
            $post = Yii::$app->request->post();
            unset($post['phone']);
            if ($user->load($post, '') && $user->modifyUserinfo()) {
                return ['code' => 200];
            } else {
                if ($user->hasErrors()) {
                    return [
                        'code' => 404,
                        'msg' => current($user->getFirstErrors())
                    ];
                } else {
                    return [
                        'code' => 500,
                        'msg' => '未知错误',
                    ];
                }
            }
        }
    }

    public function actionSignup() {
        $phone = Yii::$app->request->post('phone');
        $password = Yii::$app->request->post('password');
        $verifyCode = Yii::$app->request->post('verifyCode');
        $inviteCode = Yii::$app->request->post('inviteCode');
        if (empty($phone) || empty($password) || empty($verifyCode)) {
            return [
                'code' => 400,
                'msg' => '参数错误'
            ];
        }
        $res = Sms::verifyAuthCode($phone, $verifyCode, Sms::CODE_TYPE_SIGNUP);
        if ($res['err'] != 0) {
            return [
                'code' => 402,
                'msg' => $res['msg']
            ];
        }

        try {
            $user = new User();
            $user->uid = \common\models\User::generateUid();
            $user->phone = $phone;
            $user->invite_code = User::generateInviteCode($phone);
            !is_null($inviteCode) && $user->invite_code_signup = $inviteCode;
            $user->setPassword($password);
            $user->generateAuthKey();
            $res = $user->save(false);
            if ($res) {
                $user->refresh();
                if ($inviteCode) {
                    $tmp = Fund::inviteSend($inviteCode, $user->id);
                    if ($tmp['err'] != 0) {
                        return [
                            'code' => 402,
                            'msg' => $tmp['msg']
                        ];
                    }
                }
                Alarm::business('用户id：' . $user->uid . ', 电话：' . $user->phone, '新注册用户');
                return [
                    'code' => 200,
                    'msg' => '注册成功'
                ];
            } else {
                Yii::error(__METHOD__ . '|err:' . var_export($user->getErrors(), true), 'Exception');
                return [
                    'code' => 401,
                    'msg' => '未知错误'
                ];
            }
        } catch (\Exception $e) {
            if ($e->getCode() === 23000) {//phone重复
                if (strpos($e->getMessage(), 'for key \'phone\'')) {
                    return [
                        'code' => 403,
                        'msg' => '该手机号码已注册'
                    ];
                } else {
                    Yii::error('code:' . $e->getCode() . '|msg:' . $e->getMessage(), 'Exception');
                    return [
                        'code' => 500,
                        'msg' => '系统繁忙'
                    ];
                }
            } else {
                Yii::error('code:' . $e->getCode() . '|msg:' . $e->getMessage(), 'Exception');
                return [
                    'code' => 500,
                    'msg' => '系统繁忙'
                ];
            }
        }
    }

    public function actionLogin() {
        $loginType = Yii::$app->request->post('type');
        if (empty($loginType) || !in_array($loginType, [
                User::LOGIN_TYPE_PW,
                User::LOGIN_TYPE_VERIFYCODE
            ])
        ) {
            return [
                'code' => 407,
                'msg' => '登录类型错误'
            ];
        }
        $model = new User();
        if ($loginType == User::LOGIN_TYPE_PW) {
            $model->setScenario(User::SCENARIO_LOGIN_PW);
        } elseif ($loginType == User::LOGIN_TYPE_VERIFYCODE) {
            $model->setScenario(User::SCENARIO_LOGIN_VERIFYCODE);
        }
        if ($model->load(Yii::$app->request->post(), '') && $model->login()) {
            return [
                'code' => 200,
                'msg' => '登录成功'
            ];
        } else {
            if ($model->hasErrors()) {
                return [
                    'code' => 404,
                    'msg' => current($model->getFirstErrors())
                ];
            } else {
                return [
                    'code' => 500,
                    'msg' => '未知错误',
                ];
            }
        }
    }

    public function actionLogout() {
        if (!Yii::$app->user->isGuest) {
            Yii::$app->user->logout();
        }
        return [
            'code' => 200,
        ];
    }

    public function actionPassword() {
        $newPassword = Yii::$app->request->post('newPassword');
        if (empty($newPassword)) {
            return [
                'code' => 403,
                'msg' => '参数错误'
            ];
        }
        $type = Yii::$app->request->post('type');
        if ($type == 1) {//登录状态
            $oldPassword = Yii::$app->request->post('oldPassword');
            if (empty($oldPassword)) {
                return [
                    'code' => 403,
                    'msg' => '参数错误'
                ];
            } elseif ($oldPassword == $newPassword) {
                return [
                    'code' => 404,
                    'msg' => '新旧密码相同',
                ];
            }
            /* @var $user User */
            $user = Yii::$app->user->getIdentity();
            if (!$user) {
                return [
                    'code' => 400,
                    'msg' => '用户未登录'
                ];
            }
            if (!$user->validatePassword($oldPassword)) {
                return [
                    'code' => 401,
                    'msg' => '旧密码错误'
                ];
            }
            $user->setPassword($newPassword);
            $user->removePasswordResetToken();
            $user->save(false);
            return ['code' => 200];
        } elseif ($type == 2) {
            $token = Yii::$app->request->post('token');
            if (empty($token)) {
                return [
                    'code' => 403,
                    'msg' => '参数错误'
                ];
            }
            $user = User::findByPasswordResetToken($token);
            if (!$user) {
                return [
                    'code' => 402,
                    'msg' => 'token错误'
                ];
            }
            $user->setPassword($newPassword);
            $user->removePasswordResetToken();
            $user->save(false);
            return ['code' => 200];
        }
        return ['code' => 500];
    }

    public function actionSmsverify() {
        $type = Yii::$app->request->post('type');
        $phone = Yii::$app->request->post('phone');
        $verifyCode = Yii::$app->request->post('verifyCode');
        if (!in_array($type, Sms::CODE_TYPE_ALL) || empty($verifyCode)) {
            return [
                'code' => 400,
                'msg' => '参数错误'
            ];
        }
        $res = Sms::verifyAuthCode($phone, $verifyCode, $type);
        if ($res['err'] != 0) {
            return [
                'code' => 402,
                'msg' => $res['msg']
            ];
        }
        if ($type == Sms::CODE_TYPE_LOGIN) {
            return [
                'code' => 200,
            ];
        } elseif ($type == Sms::CODE_TYPE_PASSWORD_RESET) {
            /* @var $user User */
            $user = User::findOne([
                'status' => User::STATUS_ACTIVE,
                'phone' => $phone,
            ]);
            if (!$user) {
                Yii::warning('用户不存在,尝试重置密码', __METHOD__);
                return [
                    'code' => 401,
                    'msg' => '用户不存在'
                ];
            }
            $user->generatePasswordResetToken();
            $user->save(false, ['password_reset_token']);
            return [
                'code' => 200,
                'token' => $user->password_reset_token,
            ];
        }
        return ['code' => 500];
    }

    public function actionSmsrequest() {
        $type = Yii::$app->request->post('type');
        $phone = Yii::$app->request->post('phone');
        if (!in_array($type, Sms::CODE_TYPE_ALL)) {
            return [
                'code' => 400,
                'msg' => '参数错误'
            ];
        }
        //TODO
        if (strlen($phone) != 11 || !preg_match('/^1[3|4|5|7|8][0-9]\d{8}$/', $phone)) {
            return ['code' => 401, 'msg' => '手机号格式错误'];
        }
        $limitSec = 60;
        $lastCode = Sms::getLastCode($phone);
        if ($lastCode && time() - $lastCode[2] < $limitSec) {
            return [
                'code' => 401,
                'msg' => $limitSec . '秒后才能再次发送'
            ];
        }
        $dayCount = Yii::$app->redis->hincrby(sprintf(Sms::AUTH_CODE_COUNT_HASH_KEY, date('Ymd')), $phone, 1);
        if ($dayCount >= 15) {
            return [
                'code' => 402,
                'msg' => '超出每日频率限制',
            ];
        }
        $res = Sms::sendAuthCode($phone, $type);
        if ($res) {
            return [
                'code' => 200,
                'limitSec' => $limitSec,
            ];
        } else {
            return [
                'code' => 403,
            ];
        }
    }

    public function actionGetname() {
        $inviteCode = Yii::$app->request->get('inviteCode');
        $model = User::findOne(['invite_code' => $inviteCode]);
        if (!$model) {
            return [
                'code' => 404,
                'msg' => 'not found',
            ];
        }
        return [
            'code' => 200,
            'data' => [
                'username' => \common\logic\User::getNameByModel($model),
            ]
        ];
    }
}
